<?php
namespace Modules\Activity\Entities\Lottery;

use Modules\Activity\Entities\BaseActivityModel;
use Illuminate\Database\Eloquent\Builder;

use Modules\Activity\Entities\Lottery\Record;
use Modules\Activity\Entities\Lottery\Ticket;

use Modules\Order\Entities\BaseOrder as Order;
use ThrowException;
use Cache;

// 抽奖
class Activity extends BaseActivityModel
{
    protected $table = 'lottery_activity';

    public $activityType = 'lottery';
    public $activityTypeText = '抽奖';

    // protected $guarded = ['union_status', 'union_status_text', 'type_text'];

    // protected $appends = ['union_status', 'union_status_text'];

    protected $casts = [
        'images' => 'json',
        'detail_images' => 'json',
        'join_codes' => 'json'
    ];

    public function getType($type) 
    {
        $map = [
            'base_sku_type' => 'lottery',
            'node_type' => 'lottery'
        ];

        return @$map[$type];
    }

    // 
    public function getNodeEntity()
    {
        return $this;
    }

    // 所有sku
    public function skus()
    {
        return $this->hasMany('\Modules\Activity\Entities\Lottery\Sku', 'activity_id')->orderBy('list_weight', 'desc')->orderBy('id', 'asc');
    }

    // 所有参与记录
    public function records()
    {
        return $this->hasMany('\Modules\Activity\Entities\Lottery\Record', 'activity_id');
    }

    // 所有抽奖码
    public function tickets()
    {
        return $this->hasMany('\Modules\Activity\Entities\Lottery\Ticket', 'activity_id');
    }

    public function lucky_records()
    {
        return $this->records()->where('is_lucky_user', 1);
    }

    // public function current_session_tickets()
    // {
    //     return $this->tickets()->where('session', $this->current_session);
    // }

    // 所有受邀者
    public function invitees()
    {
        return $this->hasMany('\Modules\Activity\Entities\Lottery\InviteeRecord', 'activity_id');
    }

    // 每期抽取奖品数量
    public function updatePrizeTotal()
    {
        $this->update([
            'prize_total' => $this->skus()->sum('per_session_stock')
        ]);
    }

    // // 某用户是否已参与过
    public function isUserJoin($user, $session = NULL)
    {
        if (!$user)
            return false;

        $session = $session ?: $this->current_session;

        return $this->records()->where('session', $session)->where('user_id', $user->id)->first();
    }

    // 是否中奖
    public function isLuckyUser($user, $session = NULL)
    {
        if (!$user)
            return false;

        $session = $session ?: $this->current_session;

        return $this->records()->lucky()->where('session', $session)->where('user_id', $user->id)->first();
    }

    // 计算受邀者数量
    public function calcInviteeTotal($user)
    {
        if (!$user)
            return 0;

        return $this->invitees()->where('user_id', $user->id)->count();
    }

    // 计算某用户签号数量
    public function calcTicketTotal($user, $session = NULL)
    {
        if (!$user)
            return 0;

        // $session = $session ?: $this->current_session;

        return $this->tickets()->where('user_id', $user->id)->count();
    }

    // 查找或创建当期参与记录
    public function sendTicketTo($user, $total, $options = [])
    {
        $record = $this->records()->where('user_id', $user->id)->where('session', $this->current_session)->first();

        if (!$record) {
            // 创建参与记录
            $record = Record::createWith($this, $user, $options);
        }

        $list = [];

        // 创建抽奖码 (一共需要创建$total张)
        for ($i=0; $i<$total; $i++) {
            $ticket = Ticket::createWith($record, $user, 'box_reward', $options);

            array_push($list, $ticket);
        }

        // 检查状态
        $this->checkStatus();

        return $list;
    }

    // 是否助力过
    public function isAcceptedInvite($inviter, $invitee) 
    {
        if (!$invitee) {
            return false;
        }

        return $this->invitees()->where([
            'user_id' => $inviter->id,
            'invitee_id' => $invitee->id
        ])->first();
    }

    // 增加助力记录
    public function addInvite($inviter, $invitee)
    {
        $activityRecord = $this->records()->where('user_id', $inviter->id)->orderBy('id', 'desc')->first();

        // 是否是新用户
        $isNewUser = $invitee->isNewUser();

        // 奖励的签号数量
        $rewardTotal = $isNewUser ? $this->new_user_reward_ticket : $this->old_user_reward_ticket;

        // 创建助力记录
        $this->invitees()->create([
            'uuid' => uniqid(),
            'user_id' => $inviter->id,
            'activity_record_id' => $activityRecord->id,
            'session' => $this->current_session,
            'invitee_id' => $invitee->id,
            'is_new_user' => $isNewUser,
            'ticket_total' => $rewardTotal
        ]);

        // 创建签号
        for ($i=0; $i < $rewardTotal; $i++) { 
            // 创建抽奖码
            $ticket = Ticket::createWith($activityRecord, $inviter, 'invite', [
                'invitee' => $invitee
            ]);
        }

        $this->checkStatus();

        return [
            $isNewUser, 
            $rewardTotal
        ];
    }

    // 开奖
    public function runDrawLottery()
    {
        // 禁止多次触发抽奖函数
        $cachedKey = 'lottery_draw_' . $this->uuid . $this->current_session;
        $lock = Cache::lock($cachedKey, 100);
        if (!$lock->get()) {
            // 无法锁定当前函数
            return false;
        }

        // 抽取
        $luckyUserTotal = $this->skus()->sum('per_session_stock');

        if ($luckyUserTotal <= 0) {
            return false;
        }

        // 所有用户记录
        $userRecords = $this->records()->where('session', $this->current_session)->withCount(['tickets'])->get();

        // 按签号抽取用户
        $luckyUserRecords = pickLuckySku($userRecords, 'tickets_count', $luckyUserTotal);

        // $this->skus()->update([
        //     'current_allot_total' => 0
        // ]);

        $skus = $this->skus()->where('stock', '>', 0)->get();
        $skuIds = [];
        foreach ($skus as $sku) {
            for ($i=0; $i<$sku->per_session_stock; $i++) {
                array_push($skuIds, $sku->id);
            }
        }


        foreach ($luckyUserRecords as $key => $record) {

            if (count($skuIds) <= $key) {
                break;
            }

            $user = $record->user;

            // 取出一个随机的礼品
            $sku = $skus->where('id', $skuIds[$key])->first();

            $ticket = $record->tickets()->inRandomOrder()->first();
            
            // 为用户创建package sku
            $packageSku = $sku->sendToUser($user, $this, $ticket);
            $sku->addSales(1);

            if ($ticket) {
                $ticket->update([
                    'status' => 1,
                    'sku_id' => $sku->id,
                    'package_sku_id' => $packageSku->id
                ]); 
            }

            // 标记为中奖
            $record->update([
                'is_lucky_user' => 1
            ]);
        }

        return true;
    }

    // 检查是否达到开奖条件并开奖
    public function checkStatus()
    {
        // \Log::error('union_status  ' . $this->union_status);
        
        if ($this->union_status !== 'working')
            return false;

        // \Log::error('count  ' . $this->records()->where('session', $this->current_session)->count());

        $flag = false;

        if ($this->emit_type === 'time') {
            // 固定时间开奖
            if (strtotime($this->emit_time) <= time()) {
                $flag = true;
            }
        }
        elseif ($this->emit_type === 'user_total') {
            // 按参与人数触发
            if ($this->records()->where('session', $this->current_session)->count() >= $this->emit_user_total) {
                $flag = true;
            }
        }
        elseif ($this->emit_type === 'ticket_total') {
            // 按签号数量触发
            if ($this->tickets()->where('session', $this->current_session)->count() >= $this->emit_ticket_total) {
                $flag = true;
            }
        }


        if ($flag) {
            // 开奖
            $this->runDrawLottery();

            // 把所有未开奖的设置为未中奖
            $this->tickets()->where('session', $this->current_session)->where('status', 0)->update([
                'status' => 2
            ]);

            // 如果当前期数未达到开奖期数，则开下一期 
            if ($this->current_session < $this->session_total) {
                $this->current_session += 1;
                $this->save();
            }
            else {
                $this->update([
                    'end_at' => now()
                ]);
            }
        }

        return true;
    }

    // 抽出幸运sku
    // public function pickLuckySkus($total, $user = NULL, $order = NULL, $optoins = [])
    // {
    //     // 取哪一个福袋
    //     $skus = $this->skus()->onStock()->get();

    //     $luckyList = pickLuckySkuMaps($skus, 'odds', $total);

    //     return $luckyList;
    // }

    // 试玩开sku
    // public function pickLuckySkusForTry($total, $user = NULL, $order = NULL, $optoins = [])
    // {
    //     // 取哪一个福袋
    //     $skus = $this->skus()->where('level', '>', 3)->orderBy('level', 'desc')->orderBy('odds', 'asc')->onStock()->take(15)->get();

    //     $luckyList = pickLuckySkuMaps($skus, 'odds', $total);

    //     return $luckyList;
    // }

    // 订单完成支付
    public function orderPaidListenerSync($order)
    {
        // 创建参与记录
        $user = $order->user;

        // 创建参与记录
        $record = Record::createWith($this, $user, [
            'order' => $order
        ]);

        // 创建抽奖码
        $ticket = Ticket::createWith($record, $user, 'join', [
            'order' => $order
        ]);

        // 检查状态
        $this->checkStatus();

        return true;
    }

    // 流水满*自动报名
    public function waterFullAuto()
    {
        // 每10分钟统计一次
        if ( date('i')%10 != 0 ) return false;
        $s1 = '流水满';
        $s2 = '自动报名';

        $t_d = date('Y-m-d');
        // 非当日创建的 跳过
        if ( $this->created_at < $t_d ) return false;

        if ( !$this->sub_title || substr($this->sub_title, 0, strlen($s1)) !== $s1 || substr($this->sub_title, strpos($this->sub_title, $s2)) !== $s2 ) return true;

        $money = str_replace([$s1,$s2], '', $this->sub_title) * 1;

        if ( !($money >= 1) ) return false;

        $list = Order::paid()->where([
            'type' => 'activity',
            ['completed_at', '>', $t_d],
            ['user_id', '>', 500]
        ])->whereIn('status', [8,9])
            ->groupBy('user_id')
            ->having('amount', '>=', $money*100)
            ->get(\DB::raw('sum(redpack_discount + pay_money_price) amount, user_id'));

        // 符合条件的用户
        foreach ( $list as $k => $v ){
            if ( $v->amount < $money*100 ) continue;
            $u = (object) array('id' => $v->user_id);
            if ( $this->isUserJoin($u) ) continue;
            $code = rand(1000, 9999) . strVal(time()) . $v->user_id . '0' . rand(100000, 999999);
            $code = substr($code, -16);

            $order = new Order([
                'uuid' => uniqid(),
                'user_id' => $v->user_id,
                'product_total' => 1,
                'sku_total' => 1,
                'number' => 'A' . date('mdHis') . $v->user_id . rand(100, 999),
                'pay_number' => 'A' . date('mdHis') . $v->user_id . rand(100, 999),
                'code' => $code,
                'pay_type' => 'none',
                'miniapp_type' => 'wechat',
                'product_money_price' => 0,
                'product_score_price' => 0,
                'order_money_price' => 0,
                'order_score_price' => 0,
                'pay_money_price' => 0,
                'pay_score_price' => 0,
                'confirmed_at' => date('Y-m-d H:i:s'),
                'auto_closed_at' => date('Y-m-d H:i:s'),
                'auto_completed_at' => date('Y-m-d H:i:s'),
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
                'type' => 'activity',
                'status' => 9,
                'pay_status' => 2,
                'node_id' => $this->id,
                'node_type' => 'lottery',
                'node_uuid' => $this->uuid,
                'brokerage_status' => 1,
                'is_add_sales' => 1,
            ]);

            $order->createAll();

            $this->orderPaidListenerSync($order);
        }

        return true;
    }

}
